package cn.mjnxin.iot.base.util;

import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.concurrent.atomic.AtomicInteger;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;

import cn.mjnxin.iot.base.domain.ChannelData;
import cn.mjnxin.iot.base.domain.SocketData;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.UnpooledByteBufAllocator;
import io.netty.channel.EventLoopGroup;
import io.netty.util.ReferenceCountUtil;

/**
 * 通用工具类
 * @author CLG 2023年10月10日
 * @version V1.0.0
 */
public class CommonUtil {
	public static final String              OS_NAME               = System.getProperty("os.name");
	
	/**
	 * 计数
	 */
	public static AtomicInteger             recieveCount;

	private static boolean                  isLinuxPlatform       = false;
	private static boolean                  isWindowsPlatform     = false;
	/**
	 * 使用堆内存ByteBuf，减少堆外内存使用，便于通过gc垃圾回收
	 */
	private static UnpooledByteBufAllocator allocator;
	
	static {
		recieveCount = new AtomicInteger(0);
		allocator = UnpooledByteBufAllocator.DEFAULT;
		if (OS_NAME != null && OS_NAME.toLowerCase().indexOf("linux") >= 0) {
			isLinuxPlatform = true;
		}
		if (OS_NAME != null && OS_NAME.toLowerCase().indexOf("windows") >= 0) {
			isWindowsPlatform = true;
		}
	}

	public static boolean isLinuxPlatform() {
		return isLinuxPlatform;
	}

	public static boolean isWindowsPlatform() {
		return isWindowsPlatform;
	}

	/**
	 * 从直接内存池中获取ByteBuf
	 * 
	 * @return
	 */
	public static ByteBuf getByteBuf() {
		return allocator.heapBuffer();
	}

	/**
	 * 从直接内存池中获取ByteBuf
	 * 
	 * @return
	 */
	public static ByteBuf getByteBuf(int capacity) {
		return allocator.heapBuffer(capacity);
	}

	/**
	 * 释放ByteBuf
	 * 
	 * @param buf
	 */
	public static void releaseByteBuf(ByteBuf buf) {
		if (buf != null) {
			ReferenceCountUtil.release(buf);
		}
	}

	/**
	 * 释放ByteBuf
	 * 
	 * @param buf
	 */
	public static void releaseData(ChannelData data) {
		SocketData socketData = data.getSocketData();
		if (socketData == null) {
			return;
		}
		ByteBuf buf = socketData.getByteBuf();
		if (buf != null) {
			ReferenceCountUtil.release(buf);
		}
	}

	/**
	 * 关闭EventLoopGroup
	 * 
	 * @param group
	 */
	public static void closeEventLoop(EventLoopGroup... group) {
		for (EventLoopGroup eventLoopGroup : group) {
			eventLoopGroup.shutdownGracefully();
		}
	}

	public static String getIpAddress(InetSocketAddress insocket) {
		InetAddress address = insocket.getAddress();
		String ip = address.toString();
		if (ip.indexOf('/') >= 0) {
			ip = ip.substring(ip.indexOf('/') + 1);
		}
		return MixUtil.formatIpAddress(ip.equals("localhost") ? "127.0.0.1" :ip,
				String.valueOf(insocket.getPort()));
	}
	
	/**
	 * Reference from Command
	 * 
	 * @param appName
	 * @param args
	 * @param options
	 * @param parser
	 * @return
	 */
	public static CommandLine parseCmdLine(final String appName, String[] args, Options options,
			CommandLineParser parser) {
		HelpFormatter hf = new HelpFormatter();
		hf.setWidth(110);
		CommandLine commandLine = null;
		try {
			commandLine = parser.parse(options, args);
			if (commandLine.hasOption('h')) {
				hf.printHelp(appName, options, true);
				return null;
			}
		} catch (ParseException e) {
			hf.printHelp(appName, options, true);
		}

		return commandLine;
	}
}
